package com.learning.spring.ioc.bean.code;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.stereotype.Component;

/**
 * ClassName: CodeServiceFactoryBean
 * Description: 自定义工厂后置处理器
 * 实现在Spring 容器启动阶段动态的注入自定义的 Bean，保证动态注入的 Bean 也可以被 AOP 所增强，需要实现 Bean 工厂后置处理器
 * Date: 2018/8/16 21:37 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
@Component
public class CodeBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        // DefaultListableBeanFactory 实现了 ConfigurableListableBeanFactory接口
        // 提供了可扩展配置、循环枚举的功能，可以通过此类实现 Bean 的动态注入
        DefaultListableBeanFactory factory = (DefaultListableBeanFactory) beanFactory;

        // 通过 BeanDefinitionBuilder 创建 Bean 定义
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CodeBean.class);

        // 注入。设置属性 codeReferenceBean，此属性引用已经定义的 Bean:codeReferenceBean
        builder.addPropertyReference("codeReferenceBean", "codeReferenceBean");

        // 注册 Bean 定义
        factory.registerBeanDefinition("codeBean", builder.getRawBeanDefinition());

        // 也直接注册一个 Bean 实例
        factory.registerSingleton("codeBean2", new CodeBean());

    }
}

class CodeBean {
    public CodeBean() {
        System.out.println("CodeBean 被实例化了~~");
    }
}

@Component
class CodeReferenceBean {
    public CodeReferenceBean() {
        System.out.println("CodeReferenceBean 被实例化了~~");
    }
}
